#ifndef THREAD_POOL_H
#define THREAD_POOL_H

#include <mutex>
#include <condition_variable>
#include <queue>
#include <thread>
#include <functional>
#include <assert.h>
//定义的线程池类，线程池的大小默认是8
class ThreadPool
{
public:
    //线程池的构造函数，线程池的大小默认是8
    explicit ThreadPool(size_t threadCount = 8):pool_(std::make_shared<Pool>())
    {
        //断言线程池的大小是否大于0
        assert(threadCount > 0);
        //循环创建线程池中的线程
        for(size_t i = 0;i < threadCount;++i)
        {
            //调用了C++11中的线程调用，并使用了lambda表达式
            //lambda表达式的参数是一个pool的结构体，并将pool_的值赋值给他
            std::thread([pool = pool_]
            {
                //首先，将线程加锁，防止在操作任务队列时，有其他线程在操作任务队列
                std::unique_lock<std::mutex> locker(pool->mtx);
                //循环
                while(1)
                {
                    //如果pool里面的任务队列不为空
                    if(!pool->tasks.empty())
                    {
                        //从任务队列中取出一个任务
                        auto task = std::move(pool->tasks.front());
                        //从pool的任务队列中弹出这个任务
                        pool->tasks.pop();
                        //解锁
                        locker.unlock();
                        //执行任务
                        task();
                        //加锁
                        locker.lock();
                    }
                    //如果线程池已经关闭了，就结束循环
                    else if(pool->isClosed) break;
                    //如果任务队列为空，就等待
                    else pool->cond.wait(locker);
                }
                //将线程和线程池解绑，这样主线程就不用特地等待了
            }).detach();
        }
    }
    //默认构造函数
    ThreadPool() = default;
    //默认移动构造
    ThreadPool(ThreadPool&&) = default;
    //默认析构函数
    ~ThreadPool() 
    {
        //如果线程池存在
        if(static_cast<bool>(pool_))
        {
            //先将线程加锁
            std::lock_guard<std::mutex> locker(pool_->mtx);
            //将线程池关闭
            pool_->isClosed = true;
            //通知所有线程
            pool_->cond.notify_all();
        }
        //如果线程不存在，就通知所有线程
        pool_->cond.notify_all();
    }
    //添加任务的函数
    template<class F>
    void AddTask(F&& task)
    {
        //先将线程池加锁
        std::lock_guard<std::mutex> locker(pool_->mtx);
        //将任务添加到任务队列中
        pool_->tasks.emplace(std::forward<F>(task));
        //通知一个线程
        pool_->cond.notify_one();
    }
private:
    //线程池的Pool结构体，里面包含了线程池的互斥锁，条件变量，是否关闭，任务队列
    struct Pool  
    {
        std::mutex mtx;
        std::condition_variable cond;
        bool isClosed;
        std::queue<std::function<void()>> tasks;
    };
    //线程池的智能指针
    std::shared_ptr<Pool> pool_;
};
#endif